Skip to content

Conversation

@HeatCrab
Copy link
Collaborator

@HeatCrab HeatCrab commented Nov 22, 2025

This PR implements basic U-mode (User Mode) execution for tasks, addressing Issue #19 where tasks executing in M-mode could bypass isolation by modifying privileged CSRs. This change is essential for PMP (Physical Memory Protection) to function correctly, as PMP only affects U-mode and S-mode.

Tasks now start in user mode and interact with the kernel through a syscall interface based on the ecall trap mechanism. The kernel dispatcher has been refactored to support architecture-specific implementations through weak linking, while the RISC-V backend provides an ecall wrapper following standard calling conventions. Exception handling has been extended to recognize and service user mode traps, maintaining proper privilege boundaries throughout task execution.

Related to #19


Summary by cubic

Enables user-mode execution on RISC-V with an ecall-based syscall path to enforce privilege separation and make PMP effective. Addresses the isolation issue where tasks could modify privileged CSRs in M-mode (Issue #19).

  • New Features

    • Tasks start in U-mode (MPP set to USER).
    • Syscalls use ecall following RISC-V ABI; arch-specific implementation added in arch/riscv/entry.c.
    • Trap handler services U-mode ecalls: advances mepc, extracts args, dispatches, and returns via a0.
  • Refactors

    • Syscall dispatcher marked as weak to allow architecture-specific overrides.
    • Build updated to include entry.o in HAL objects.

Written for commit e2eec20. Summary will update automatically on new commits.

Allows architecture-specific syscall implementations to override
the generic dispatcher at link time for privilege separation.
Implements syscall interface using the ecall instruction to trap into
M-mode from user space. Follows RISC-V calling convention for system
call arguments and return values.

Introduces a dedicated file for kernel entry mechanisms following
Linux conventions. This separation clarifies the distinction between
trap-based entry and generic syscall dispatch logic.
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="arch/riscv/hal.c">

<violation number="1" location="arch/riscv/hal.c:334">
Syscall handler reads the wrong registers from the ISR frame, so the kernel receives an incorrect syscall number and arguments.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

arch/riscv/hal.c Outdated
isr_frame[31] = new_epc;

/* Extract syscall arguments from ISR frame */
int syscall_num = isr_frame[17];
Copy link

@cubic-dev-ai cubic-dev-ai bot Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Syscall handler reads the wrong registers from the ISR frame, so the kernel receives an incorrect syscall number and arguments.

Prompt for AI agents
Address the following comment on arch/riscv/hal.c at line 334:

<comment>Syscall handler reads the wrong registers from the ISR frame, so the kernel receives an incorrect syscall number and arguments.</comment>

<file context>
@@ -321,6 +321,31 @@ uint32_t do_trap(uint32_t cause, uint32_t epc, uint32_t isr_sp)
+            isr_frame[31] = new_epc;
+
+            /* Extract syscall arguments from ISR frame */
+            int syscall_num = isr_frame[17];
+            void *arg1 = (void *) isr_frame[10];
+            void *arg2 = (void *) isr_frame[11];
</file context>
Fix with Cubic

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! Got the ISR frame offsets wrong - checked boot.c and corrected them.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

Adds exception handler for U-mode ecall instructions to dispatch
system calls. Extracts syscall number and arguments from the saved
register context and returns results through the same mechanism.

This design enables privilege separation by allowing user-mode tasks
to request kernel services without direct access to privileged
operations, addressing the security issue where tasks could bypass
isolation by executing in M-mode.
Tasks are now initialized to execute in U-mode rather than M-mode,
enabling proper privilege isolation. The MPP field in mstatus is set
to USER instead of MACH during context initialization.
@HeatCrab HeatCrab force-pushed the u-mode/basic-support branch from 9ec8f5c to e2eec20 Compare November 22, 2025 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant